mod chat_loop;
#[cfg(test)]
mod chat_test;
mod openai_client;
pub mod tool_functions;

use crate::models::{ChatMessage, ProjectConfig};
use anyhow::{anyhow, Context, Result};
use dotenv::dotenv;
use openai_client::{ChatRequest, OpenAIClient, ResponseFormat};
use std::env;
use tool_functions::tools_model::TOOLS_JSON;

const DEFAULT_MAX_TOKEN: u32 = 9000;
const AI_API_KEY: &str = "AI_API_KEY";
const AI_SERVER_BASE_URL: &str = "AI_SERVER_BASE_URL";
const AI_MODEL: &str = "AI_MODEL";

const DEFAULT_API_BASE_URL: &str = "https://api.deepseek.com";
const DEFAULT_MODEL: &str = "deepseek-chat";

pub async fn chat(
    messages: &[ChatMessage],
    temperature: f32,
    context: &Option<ProjectConfig>,
) -> Result<String> {
    dotenv().ok();
    let api_key = env::var(AI_API_KEY).context(format!(
        "API Key not found in environment variables:{}",
        AI_API_KEY
    ))?;
    let base_api = env::var(AI_SERVER_BASE_URL).unwrap_or(DEFAULT_API_BASE_URL.to_string());
    let model = env::var(AI_MODEL).unwrap_or(DEFAULT_MODEL.to_string());

    println!("url:{}", base_api);
    println!("model:{}", model);
    let client = OpenAIClient::new(&api_key, &base_api);

    let request = ChatRequest {
        messages: messages.to_vec(),
        model,
        max_tokens: Some(DEFAULT_MAX_TOKEN),
        temperature: Some(temperature),
        response_format: ResponseFormat {
            r#type: "text".to_string(),
        },
        tools: Some(TOOLS_JSON.clone()),
        tool_calls: None,
    };

    match client.chat(&request, context).await {
        Ok(response) => {
            println!("Response ID: {}", response.id);
            let mut result = String::from("");
            for choice in response.choices {
                if let Some(content) = choice.message.content {
                    result.push_str(&content);
                }
            }
            println!(
                "Token Usage: prompt_tokens={}, completion_tokens={}, total_tokens={}",
                response.usage.prompt_tokens,
                response.usage.completion_tokens,
                response.usage.total_tokens
            );
            Ok(result)
        }
        Err(e) => {
            println!("client.chat encountered error: {:?}", e);
            Err(anyhow!("Error: {}", e))
        }
    }
}
